﻿//
// $HeadURL: http://codeka-memcache.googlecode.com/svn/trunk/Codeka.Memcache/ServerPoolMap.cs $
// $Revision: 3 $
// $Author: dean.codeka $     $Date: 2010-02-13 13:03:08 +0000 (Sat, 13 Feb 2010) $
//
// Copyright © 2009-2010 Dean Harding, all rights reserved.
//

using System;
using System.Collections.Generic;
using Codeka.Memcache.Config;

namespace Codeka.Memcache
{
    /// <summary>
    /// So that we don't have to construct the <see cref="ServerMap"/> over and
    /// over, we keep a mapping of <see cref="IMemcacheConfiguration"/>,
    /// <see cref="ServerPool"/>s.
    /// </summary>
    /// <remarks>
    /// <para>Constructing the <see cref="ServerPool"/> can be expensive (because it
    /// need to generate the server hashes), we keep a static map of them in this
    /// class, and index them by the <see cref="IMemcacheConfiguration"/>. The idea
    /// is that if you pass the same configuration every time, we'll give you the
    /// exact same instance of the <see cref="ServerPool"/>.</para>
    /// <para>We keep only <see cref="WeakReference"/>s to the <see cref="ServerPool"/>s
    /// in the dictionary. The idea is that if you're not using it very frequently,
    /// it'll get GC'd (so we don't have them hanging around forever)</para>
    /// </remarks>
    public class ServerPoolMap
    {
        private Dictionary<IMemcacheConfiguration, WeakReference> pools;

        /// <summary>
        /// Constructs a new <see cref="ServerPoolMap"/>.
        /// </summary>
        public ServerPoolMap()
        {
            pools = new Dictionary<IMemcacheConfiguration, WeakReference>();
        }

        /// <summary>
        /// Gets the <see cref="ServerPool"/> for the given <see cref="IMemcacheConfiguration"/>.
        /// </summary>
        public ServerPool GetServerPool(IMemcacheConfiguration config)
        {
            ServerPool sp;
            WeakReference wr;
            if (pools.TryGetValue(config, out wr))
            {
                sp = wr.Target as ServerPool;
                if (sp != null)
                    return sp;
            }

            // if we don't have it (or it was GC'd) then construct a new one
            sp = new ServerPool(config);
            pools[config] = new WeakReference(sp);

            return sp;
        }
    }
}
